package com.example.demo.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.Goods;
import com.example.demo.entity.Role;
import com.example.demo.entity.User;
import com.example.demo.entity.UserRole;
import com.example.demo.entity.vo.UserVo;
import com.example.demo.exception.ApplicationException;
import com.example.demo.mapper.RoleMapper;
import com.example.demo.mapper.UserRoleMapper;
import com.example.demo.service.RoleService;
import com.example.demo.service.UserRoleService;
import com.example.demo.service.UserService;
import com.example.demo.mapper.UserMapper;
import com.example.demo.util.RedisUtil;
import com.example.demo.util.StringUtil;
import com.example.demo.vo.Result;
import com.example.demo.vo.ResultCode;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* @author 三石
* @description 针对表【user(系统用户)】的数据库操作Service实现
* @createDate 2024-05-06 21:39:48
*/
@Slf4j
@Service
@AllArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{

    private RoleMapper roleMapper;

    private PasswordEncoder passwordEncoder;

    private UserRoleService userRoleService;

    private RoleService roleService;

    private UserRoleMapper userRoleMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    RedisUtil redisUtil;

    /**
     *
     * @param username 用户名
     * @return
     */
    @Override
    public String findPasswordByUsername(String username) {
        if(ObjectUtil.isEmpty(username)){
            return null;
        }
        return baseMapper.selectPasswordByUsername(username);
    }

    @Override
    public List<Role> findRolesByUsername(String username) {
        if (ObjectUtil.isEmpty(username)){
            /** 返回空数组 */
            return Collections.emptyList();
        }
        return roleMapper.selectRoleByIds(baseMapper.selectRoleIdsByUsername(username));
    }

    @Override
    public void createNormalUser(User user) {
        // 1. 非空校验
        if (user == null || StringUtil.isEmpty(user.getUsername()) || StringUtil.isEmpty(user.getPassword())
                || StringUtil.isEmpty(user.getNickname())) {
            // 打印日志
            log.warn(ResultCode.CLIENT_A0100.toString());
            // 抛异常
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0001));
        }

        // 2. 按用户名查询用户信息
        User existUser = baseMapper.selectByUserName(user.getUsername());
        if (existUser != null) {
            // 打印日志
            log.warn("用户已存在");
            // 抛出异常
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0100));
        }

        // 3. 新增用户, 设置默认值
        user.setGender("0");
        user.setStatus(1);
        // 当前日期
        LocalDateTime date = LocalDateTime.now();
        user.setCreateTime(date);
        user.setUpdateTime(date);

        // 4. 写入数据库
        int row = baseMapper.insert(user);
        if (row != 1) {
            log.warn("注册失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0100));
        }

        // 5. 默认给用户设置普通用户
        // 查出普通用户的id
        QueryWrapper<Role> wrapper = new QueryWrapper<>();
        wrapper.eq("rolename", "普通用户");
        Role role = roleMapper.selectOne(wrapper);
        // 设置角色
        UserRole userRole = new UserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(role.getId());
        // 更新表
        userRoleMapper.insert(userRole);

        log.info("注册成功");
    }

    @Override
    public User login(String username, String password) {
        // 1. 非空校验
        if (StringUtil.isEmpty(username) || StringUtil.isEmpty(password)) {
            // 打印日志
            log.warn("参数校验失败");
            // 抛出异常
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }
        // 2. 按照用户名查询用户信息
        User existUser = baseMapper.selectByUserName(username);
        // 3. 对查询结果做非空校验
        if (existUser == null) {
            // 打印日志
            log.warn("登录失败,用户: " + username);
            // 抛出异常
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0003));
        }
        // 4. 对密码做校验
        if (!passwordEncoder.matches(password, existUser.getPassword())) {
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0210));
        }
        // 打印日志
        log.info("登录成功, " + "用户: " + username);
        // 登录成功
        return existUser;
    }

    @Override
    public void resetPassword(String username, String password) {
        // 1. 校验参数
        if (StringUtil.isEmpty(username) || StringUtil.isEmpty(password)) {
            // 打印日志
            log.warn("参数校验失败");
            // 抛出异常
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }
        // 2. 按照用户名查询用户信息
        User existUser = baseMapper.selectByUserName(username);

        // 3. 对查询结果做校验
        if (existUser == null || existUser.getIsDeleted() == 1) {
            // 打印日志
            log.warn("修改失败,用户: " + username);
            // 抛出异常
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0201));
        }
        if (existUser.getStatus() == 0) {
            log.warn("用户状态异常");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0006));
        }

        // 4. 密码加密
        String newPassword = passwordEncoder.encode(password);

        // 5. 构造新的对象
        User user = new User();
        user.setUsername(username);
        user.setPassword(newPassword);
        LocalDateTime dateTime = LocalDateTime.now();
        user.setUpdateTime(dateTime);
        user.setPwdResetTime(dateTime);

        // 6. 密码更新
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        //  6.1 设置更新条件
        updateWrapper.eq("username", username);
        //  6.2 调用 update 方法执行动态更新
        int row = baseMapper.update(user, updateWrapper);

        // 7. 验证是否操作成功
        if (row != 1) {
            log.warn("密码重置失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0004));
        }

        log.info("密码重置成功");

    }

    @Override
    public void modifyPassword(String username, String oldPassword, String newPassword) {
        // 1. 校验参数
        if (StringUtil.isEmpty(username) || StringUtil.isEmpty(oldPassword) || StringUtil.isEmpty(newPassword)) {
            // 打印日志
            log.warn("参数校验失败");
            // 抛出异常
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }
        // 2. 查询用户信息
        User existUser = baseMapper.selectByUserName(username);
        if (existUser == null || existUser.getIsDeleted() == 1) {
            log.warn("用户不存在!");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0005));
        }
        if (existUser.getStatus() == 0) {
            log.warn("用户状态异常");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0006));
        }
        // 3. 判断密码与数据库用户是否一致
        if (!passwordEncoder.matches(oldPassword, existUser.getPassword())) {
            log.warn("输入密码与用户密码不一致");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }
        // 4. 构造新对象
        User user = new User();
        user.setUsername(username);
        // 设置新密码
        String encode = passwordEncoder.encode(newPassword);
        user.setPassword(encode);
        LocalDateTime dateTime = LocalDateTime.now();
        user.setUpdateTime(dateTime);
        user.setPwdResetTime(dateTime);

        // 5. 调用mapper
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("username", username);
        int row = baseMapper.update(user, wrapper);

        // 验证操作是否成功
        if (row != 1) {
            log.warn("密码修改失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0004));
        }

        log.info("密码修改成功");
    }

    @Override
    public void modifyInfo(User updateUser) {
        // 1. 参数校验
        if (updateUser == null) {
            log.warn("参数校验失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }

        // 2. 校验用户状态
        User existUser = baseMapper.selectByUserName(updateUser.getUsername());
        if (existUser == null || existUser.getIsDeleted() == 1) {
            log.warn("用户不存在!");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0005));
        }
        if (existUser.getStatus() == 0) {
            log.warn("用户状态异常");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0006));
        }

        // 3. 调用mapper
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("username", updateUser.getUsername());
        int row = baseMapper.update(updateUser, wrapper);

        // 验证操作是否成功
        if (row != 1) {
            log.warn("用户信息修改失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0007));
        }

        log.info("用户信息修改成功");

    }

    @Override
    public void uploadAvatar(User updateUser) {
        // 1. 参数校验
        if (updateUser == null) {
            log.warn("参数校验失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }

        // 2. 校验用户状态
        User existUser = baseMapper.selectByUserName(updateUser.getUsername());
        if (existUser == null || existUser.getIsDeleted() == 1) {
            log.warn("用户不存在!");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0005));
        }
        if (existUser.getStatus() == 0) {
            log.warn("用户状态异常");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0006));
        }

        // 3. 调用mapper
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("username", updateUser.getUsername());
        int row = baseMapper.update(updateUser, wrapper);

        // 验证操作是否成功
        if (row != 1) {
            log.warn("用户头像上传失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0007));
        }

        log.info("用户上传头像成功");

    }

    @Override
    public Long getUserId(String username) {
        // 1. 校验参数
        if (StringUtil.isEmpty(username)) {
            log.warn("参数校验失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }

        // 2. 调用mapper拿到用户信息
        User existUser = baseMapper.selectByUserName(username);
        if (existUser == null || existUser.getIsDeleted() == 1) {
            log.warn("用户不存在!");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0005));
        }
        if (existUser.getStatus() == 0) {
            log.warn("用户状态异常");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0006));
        }

        // 3. 拿到用户id并返回
        Long id = existUser.getId();
        if (id == null || id < 1) {
            log.warn("用户id为非法id");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0011));
        }

        // 成功返回
        log.info("成功拿到用户id");
        return id;

    }

    @Override
    public ArrayList<String> getRoleByUsername(String username) {
        // 1. 校验参数
        if (StringUtil.isEmpty(username)) {
            log.warn("参数校验失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }
//        log.error(username);
        //2.查询角色ids
        List<Long> roleIds = baseMapper.selectRoleIdsByUsername(username);

        //3.根据角色ids查询角色
        return baseMapper.getRoleByIds(roleIds);
    }

    @Override
    public List<UserVo> getAllUserWithRole() {


        String roleList = redisTemplate.opsForValue().get("RoleList");
        if(StrUtil.isNotBlank(roleList)){
            return redisUtil.getList(roleList, UserVo.class);
        }

        // 1. 拿到所有用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        List<User> users = baseMapper.selectList(wrapper);

        // 构造返回对象
        List<UserVo> list = new ArrayList<>();

        //  遍历所有的用户, 查出角色
        for (User user : users) {
            List<Long> roleId = userRoleService.getRoleIdByUserId(user.getId());
            List<String> names = new ArrayList<>();
            for (Long id : roleId) {
                String name = roleService.getRoleNameByRoleId(id);
                names.add(name);
            }
            UserVo userVo = new UserVo();
            userVo.setId(user.getId());
            userVo.setUsername(user.getUsername());
            userVo.setNickname(user.getNickname());
            userVo.setRoleName(names);
            list.add(userVo);
        }

        redisUtil.setList(list,"RoleList");
        // 返回
        return list;
    }

    @Override
    public void modifyUserRole(Long userId, List<Long> roles) {
        // 1. 校验参数
        if (userId < 1 || roles.size() == 0) {
            log.warn("参数校验失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }

        // 2. 根据userid查出用户对象
        User existUser = baseMapper.selectById(userId);
        if (existUser == null || existUser.getIsDeleted() == 1) {
            log.warn("用户不存在!");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0005));
        }
        if (existUser.getStatus() == 0) {
            log.warn("用户状态异常");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0006));
        }

        // 3 清空之前的角色数据
        userRoleMapper.delete(new QueryWrapper<UserRole>().eq("user_id", userId));

        // 4. 调用mapper
        for (Long role : roles) {
            UserRole userRole = new UserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(role);
            int row = userRoleMapper.insert(userRole);
            if (row != 1) {
                log.warn("服务错误");
                throw new ApplicationException(Result.error(ResultCode.CLIENT_A9999));
            }
        }

        log.info("修改成功!");

    }

    @Override
    public User getUserInfoByUserId(Long userId) {

        String userInfo = redisTemplate.opsForValue().get("userInfo");
        if(StrUtil.isNotBlank(userInfo)){
            //调用工具类RedisUtil的goodsList方法，将JSON 字符串解析成list<Goods>并返回
            return redisUtil.getObject(userInfo, User.class);
        }
        // 1. 校验参数
        if (userId < 0) {
            log.warn("参数校验失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }

        // 2. 调用mapper
        User user = baseMapper.selectById(userId);
        if (user == null || user.getIsDeleted() == 1) {
            log.warn("用户不存在!");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0005));
        }
        if (user.getStatus() == 0) {
            log.warn("用户状态异常");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0006));
        }

        //存入redis
        redisUtil.setObject(user,"userInfo");
        log.info("用户查询成功!");

        return user;
    }

    @Override
    public void ModifyUserStatus(Long userId) {
        // 1. 校验参数
        if (userId < 1) {
            log.warn("参数校验失败");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0002));
        }

        // 2. 根据id查出用户对象
        User user = baseMapper.selectById(userId);
        if (user == null || user.getIsDeleted() == 1) {
            log.warn("用户不存在!");
            throw new ApplicationException(Result.error(ResultCode.CLIENT_A0005));
        }
        if (user.getStatus() == 1) {
            user.setStatus(0);
            baseMapper.updateById(user);
        } else {
            user.setStatus(1);
            baseMapper.updateById(user);
        }

        // 3. 修改成功
        log.info("修改成功");

    }


}




